/*
 *	Extended string library for C
 *
 *	Copyright (C) 2011 XiaoJSoft Studio. All Rights Reserved.
 *	Copyright (C) Ji WenCong <whs_jwc@163.com>
 *
 *	This program is free software: you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation, either version 3 of the License, or
 *	(at your option) any later version.
 *
 *	This program is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License
 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include "../include/strext.h"

/*
 *	int isNumeric(char *szExpression);
 *
 *	Determine whether the string is numeric.
 *
 *	*szExpression	->	a pointer pointed to a string.
 */
int isNumeric(char *szExpression)
{
	char *szPointer = NULL;

	for (szPointer = ((*szExpression == '-') ? szExpression + 1 : szExpression); *szPointer != '\0'; szPointer++) {
		if (((*szPointer) <= '9' && (*szPointer) >= '0') || (*szPointer) == '.') {
			continue;
		} else {
			return(0);
		}
	}

	return(1);
}

/*
 *	int strlen_ext(char *sc);
 *
 *	This is a copy of strlen() in standard libraries.
 *
 *	*sc		->	a pointer pointed to a string.
 */
int strlen_ext(char *sc)
{
	int count = 0;
	char *s = NULL;

	for (s=sc; *s!='\0'; s++) {
		count++;
	}

	return(count);
}

/*
 *	char* strfill_ext(int lpLength, char szFill);
 *
 *	Fills a string with something.
 *
 *	lpLength	->	the length of the string you want,
 *	szFill	->	what do you want to fill this string with.
 */
char* strfill_ext(int lpLength, char szFill)
{
	char *szNew = NULL;
	int lpCurrent;

	/*  Allocating enough memory areas to contain the new string  */
	szNew = (char*) malloc((lpLength + 1) * sizeof(char));
	if (szNew == NULL) {
		return(NULL);
	}

	/*  Filling the string with szFill  */
	for (lpCurrent = 0; lpCurrent <= (lpLength - 1); lpCurrent++) {
		*(szNew + lpCurrent) = szFill;
	}
	*(szNew + lpLength) = '\0';

	return(szNew);
}

/*
 *	long double strtod_ext(char *nptr, char **endptr);
 *
 *	This is a copy of strtod() in standard libraries, but fixed some crappy bugs.
 *	To convert ASCII string to floating-point number.
 *
 *	*nptr	->	a pointer pointed to a string,
 *	**endptr	->	a pointer pointed to a string pointer.
 */
long double strtod_ext(char *nptr, char **endptr)
{
	int idx;
	long double ret;
	char *endret = NULL;
	char *szOLeft = NULL;
	endret = NULL;
	ret = 0;
	for (idx = strlen_ext(nptr); idx >= 1; idx--) {
		szOLeft = NULL;

		szOLeft = strgleft_ext(nptr, idx);
		if (szOLeft == NULL) {
			*endptr = nptr;
			return(0);
		}

		/*  If the szOLeft is a full number, just return it  */
		if (isNumeric(szOLeft) == 1) {
			/*  If endptr has defined, we re-point it to (nptr + idx)  */
			if (endptr != NULL) {
				endret = nptr + idx;
			}

			/*  To get the number  */
			ret = strtod(szOLeft, NULL);

			free(szOLeft);

			break;
		}
		free(szOLeft);
	}

	if (endptr != NULL) {
		*endptr = (endret == NULL) ? nptr : endret;
	}

	return(ret);
}

/*
 *	char* strjoin_ext(char *szInput1, char *szInput2);
 *
 *	Join two string.
 *
 *	*szInput(1-2)	->	pointers pointed to two strings.
 */
char* strjoin_ext(char *szInput1, char *szInput2)
{
	char *szNew = NULL;

	/*  Join szInput1 and szInput2, We do not need to worry about 
	    whether szInput1 equals to zero  */
	kasprintf(&szNew, "%s%s", szInput1, szInput2);

	return(szNew);
}

/*
 *	int strin_ext(int lpStart, char *source, char *find);
 *
 *	This is a functional function copied from Microsoft(R) Visual Basic.
 *	To find a char or a string in another string.
 *
 *	lpStart	->	the beginning position,
 *	*source	->	the big string,
 *	*find	->	a string what you want to find in the source string.
 *
 */
int strin_ext(int lpStart, char *source, char *find)
{
	int lpCurrent, lpLength, lpFind;
	char *psSelected = NULL;

	/*  Checking input parameters  */
	if (lpStart <= 0 || source == NULL || find == NULL) {
		return(-1);
	}

	if (strlen_ext(source) <= 0 || strlen_ext(find) <= 0) {
		return(-1);
	}

	lpFind = 0;

	lpLength = strlen_ext(source);
	for (lpCurrent = lpStart; lpCurrent <= (lpLength - (strlen_ext(find) - 1)); lpCurrent++) {
		psSelected = strmid_ext(source, lpCurrent, strlen_ext(find));
		if (psSelected == NULL) {
			return(-1);
		}

		/*  Comparing two strings  */
		if (strcmp_ext(psSelected, find) == 1) {
			/*  Found it  */
			lpFind = lpCurrent;
			break;
		}

		free(psSelected);
	}

	return(lpFind);
}

/*
 *	int strin_ext_expr(int lpStart, char *source, char *find);
 *
 *	This is a functional function copied from Microsoft(R) Visual Basic.
 *	To find a char or a string in another string, but program will only search
 *	the string in bracket-level 0.
 *
 *	lpStart	->	the beginning position,
 *	*source	->	the big string,
 *	*find	->	a string what you want to find in the source string.
 */
int strin_ext_expr(int lpStart, char *source, char *find)
{
	int lpCurrent, lpLength, lpFind;
	int psInc1 = 0, psInc2 = 0;
	char *psSelected = NULL;

	/*  Checking input parameters  */
	if (lpStart <= 0 || source == NULL || find == NULL) {
		return(-1);
	}

	if (strlen_ext(source) <= 0 || strlen_ext(find) <= 0) {
		return(-1);
	}

	lpFind = 0;

	/*  Clear switches  */
	psInc1 = 0; psInc2 = 0;

	lpLength = strlen_ext(source);
	for (lpCurrent = lpStart; lpCurrent <= (lpLength - (strlen_ext(find) - 1)); lpCurrent++) {
		/*  Making sure that program is in bracket-level 0  */
		if ((*(source + lpCurrent - 1)) == '(') {
			psInc1++;
		}

		if ((*(source + lpCurrent - 1)) == ')') {
			psInc2++;
		}

		if (psInc1 != psInc2) {
			/*  If program is not in bracket-level 0, don't compare two strings  */
			continue;
		}

		psSelected = strmid_ext(source, lpCurrent, strlen_ext(find));
		if (psSelected == NULL) {
			return(-1);
		}

		/*  Comparing two strings  */
		if (strcmp_ext(psSelected, find) == 1) {
			/*  Found it  */
			lpFind = lpCurrent;
			break;
		}
		free(psSelected);
	}
	return(lpFind);
}

/*
 *	char* strmid_ext(char *source, int lpStart, int lpLength);
 *
 *	This is a functional function copied from Microsoft(R) Visual Basic.
 *
 *	*source	->	string expression from which characters are returned,
 *	lpStart	->	integer expression. Character position in Str at which 
 *				the part to be taken starts. If Start is greater than 
 *				the number of characters in Str, the Mid function returns 
 *				a zero-length string (""). Start is one based,
 *	lpLength	->	integer expression. Number of characters to return. If omitted
 *				or if there are fewer than Length characters in the text 
 *				(including the character at position Start), all characters from 
 *				the start position to the end of the string are returned.
 */
char* strmid_ext(char *source, int lpStart, int lpLength)
{
	char *strRight = NULL, *strLeft = NULL;

	/*  Checking input parameters  */
	if (source == NULL || lpStart <0 || lpLength <0) {
		return(NULL);
	}

	/*  Get the string you need to know  */
	strRight = strgright_ext(source, strlen_ext(source) - (lpStart - 1));
	strLeft = strgleft_ext(strRight, lpLength);

	if (strRight == NULL || strLeft == NULL) {
		return(NULL);
	}

	if (strRight != NULL) {
		free(strRight);
	}

	return(strLeft);
}

/*
 *	int strcmp_ext(char *cp1, char *cp2);
 *
 *	A limited version of strcmp() in standard libraries, but it's different
 *	from this function.
 *
 *	*cp(1-2)	->	string expression what we want to compare.
 */
int strcmp_ext(char *cp1, char *cp2)
{
	return((strcmp(cp1, cp2) == 0) ? 1 : 0);
}

/*
 *	char* strtrim_ext(char *source);
 *
 *	Removes all leading spaces or parsing characters from the specified character 
 *	expression, or all leading zero (0) bytes from the specified binary expression.
 *
 *	*source	->	specifies an expression of character to remove leading 
 *				spaces or 0 bytes from, respectively.
 */
char* strtrim_ext(char *source)
{
	char *lsLeft = NULL, *lsRight = NULL;

	lsLeft = strltrim_ext(source);
	lsRight = strrtrim_ext(lsLeft);

	if (lsLeft != NULL) {
		free(lsLeft);
	}

	return(lsRight);
}

/*
 *	char* strltrim_ext(char *source);
 *
 *	Removes all occurrences of white space characters from the beginning 
 *	to the first valid character in this instance.
 *
 *	*source	->	specifies an expression of character to remove leading 
 *				spaces or 0 bytes from, respectively.
 */
char* strltrim_ext(char *source)
{
	char *newString = NULL;
	int lpPointer1, lpLength, lpSlicePosition;

	/*  Checking input parameters  */
	if (source == NULL) {
		return(NULL);
	}

	lpLength = strlen_ext(source);

	lpSlicePosition = -1;

	/*  To get where the first valid character is  */
	for (lpPointer1 = 0; lpPointer1 <= (lpLength - 1); lpPointer1++) {
		if ((*(source + lpPointer1)) != ' ') {
			/*  Found it  */
			lpSlicePosition = lpPointer1;
			break;
		}
	}

	if (lpSlicePosition < 0) {
		/*  If the whole string is filled with space, return a empty string  */
		newString = (char*) malloc(1 * sizeof(char));
		if (newString == NULL) {
			return(NULL);
		}
		*newString = '\0';
	} else {
		newString = strgright_ext(source, lpLength - lpSlicePosition);
	}

	return(newString);
}

/*
 *	char* strrtrim_ext(char *source);
 *
 *	Removes all occurrences of white space characters from the last valid 
 *	character to the end of the instance.
 *
 *	*source	->	specifies an expression of character to remove leading 
 *				spaces or 0 bytes from, respectively.
 */
char* strrtrim_ext(char *source)
{
	char *newString = NULL;
	int lpPointer1, lpLength, lpSlicePosition;

	/*  Checking input parameters  */
	if (source == NULL) {
		return(NULL);
	}
	lpLength = strlen_ext(source);

	lpSlicePosition = -1;

	/*  To get where the first valid character is  */
	for (lpPointer1 = (lpLength - 1); lpPointer1 >= 0; lpPointer1--) {
		if ((*(source + lpPointer1)) != ' ') {
			lpSlicePosition = lpPointer1;
			break;
		}
	}

	if (lpSlicePosition < 0) {
		/*  If the whole string is filled with space, return a empty string  */
		newString = (char*) malloc(1 * sizeof(char));
		if (newString == NULL) {
			return(NULL);
		}

		*newString = '\0';
	} else {
		newString = strgleft_ext(source, lpSlicePosition + 1);
	}
	return(newString);
}

/*
 *	char* strgleft_ext(char *source, int slcLength);
 *
 *	Returns a string containing a specified number of characters from the 
 *	left side of a string.
 *
 *	*source	->	string expression from which the leftmost characters are 
 *				returned,
 *	slcLength	->	Integer expression. Numeric expression indicating how many 
 *				characters to return. If 0, a zero-length string ("") is 
 *				returned. If greater than or equal to the number of characters 
 *				in str, the entire string is returned.
 */
char* strgleft_ext(char *source, int slcLength)
{
	char *fsSliced = NULL;
	int lpLength;
	int lpPointer1;

	/*  Checking input parameters  */
	if (source == NULL || slcLength < 0) {
		return(NULL);
	}

	/*  Deciding the length of transfering-string  */
	if (strlen_ext(source) < slcLength) {
		lpLength = strlen_ext(source);
	} else {
		lpLength = slcLength;
	}

	/*  Allocating enough memory areas to contain the new string  */
	fsSliced = (char*) malloc((lpLength + 1) * sizeof(char));
	if (fsSliced == NULL) {
		return(NULL);
	}

	/*  Transfering the string  */
	for (lpPointer1 = 0; lpPointer1 <= lpLength; lpPointer1++) {
		if (lpPointer1 == lpLength) {
			*(fsSliced + lpPointer1) = '\0';
		} else {
			*(fsSliced + lpPointer1) = *(source + lpPointer1);
		}
	}

	return(fsSliced);
}

/*
 *	char* strgright_ext(char *source, int slcLength);
 *
 *	Returns a string containing a specified number of characters from the 
 *	right side of a string.
 *
 *	*source	->	string expression from which the rightmost characters are 
 *				returned.
 *	slcLength	->	Integer. Numeric expression indicating how many 
 *				characters to return. If 0, a zero-length string ("") is 
 *				returned. If greater than or equal to the number of characters 
 *				in str, the entire string is returned.
 */
char* strgright_ext(char *source, int slcLength)
{
	char *fsSliced;
	int lpLength, lpPointer1;

	/*  Checking input parameters  */
	if (source == NULL || slcLength < 0) {
		return(NULL);
	}

	/*  Deciding the length of transfering-string  */
	if (strlen_ext(source) < slcLength) {
		lpLength = strlen_ext(source);
	} else {
		lpLength = slcLength;
	}

	/*  Allocating enough memory areas to contain the new string  */
	fsSliced = (char*) malloc((lpLength + 1) * sizeof(char));
	if (fsSliced == NULL) {
		return(NULL);
	}

	/*  Transfering the string  */
	for (lpPointer1 = 0; lpPointer1 <= lpLength; lpPointer1++) {
		if (lpPointer1 == lpLength) {
			*(fsSliced + lpPointer1) = '\0';
		} else {
			*(fsSliced + lpPointer1) = *(source + (strlen_ext(source) - slcLength + lpPointer1));
		}
	}

	return(fsSliced);
}

/*
 *	collection* addCollection(collection *base, char *input, int key);
 *
 *	Adds an element to a Collection object.
 *
 *	*base	->	a pointer pointed to a collection object,
 *	*input	->	a string expression that specifies the element to add to the collection,
 *	key		->	a unique integer expression that specifies a key number that can be used 
 *				instead of a positional index to access this new element in the collection.
 */
collection* addCollection(collection *base, char *input, int key)
{
	collection *newOne = NULL;
	collection *lastOne = NULL;
	int handle1;

	/*  Allocating enough memory areas to contain a new node  */
	newOne = (collection*) malloc(sizeof(collection));
	if (newOne==NULL) {
		return(NULL);
	}

	/*  Allocating enough memory areas to contain a new string  */
	newOne->string = (char*) malloc((strlen_ext(input) + 1) * sizeof(char));
	if (newOne->string == NULL) {
		free(newOne);
		return(NULL);
	}

	/*  Copying the string to the node  */
	for (handle1=0; handle1 <= strlen_ext(input); handle1++) {
		if (handle1==strlen_ext(input)) {
			*(newOne->string + handle1) = '\0';
		} else {
			*(newOne->string + handle1) = *(input + handle1);
		}
	}

	/*  Setting the key and the *next  */
	newOne->key = key;
	newOne->next = NULL;

	if(base==NULL) {
		/*  No base? The new node is the base!  */
		newOne->previous = NULL;
		base = newOne;
	} else {
		/*  Looking for the last item of the collection object  */
		lastOne = getLastItem(base);

		newOne->previous = lastOne;
		lastOne->next = newOne;
	}

	return(newOne);
}

/*
 *	int editCollectionItem(collection *base, int itemKey, char *newInput, int newKey);
 *
 *	Modify a collection object.
 *
 *	*base	->	a pointer pointed to a collection object,
 *	itemKey	->	a unique integer expression that specifies a key number that can be used 
 *				instead of a positional index to access this new element in the collection.
 *	*newInput	->	the collection node we selected will be changed to this parameter,
 *	newKey	->	a new key (follow 'itemKey').
 */
int editCollectionItem(collection *base, int itemKey, char *newInput, int newKey)
{
	collection *selectedOne = NULL;
	int handle1;

	/*  Checking input parameters  */
	if (base == NULL) {
		return(0);
	}

	if (base->string == NULL) {
		return(0);
	}

	/*  Looking for the node  */
	selectedOne = getCollectionItem(base, itemKey);

	/*  Modifying the node  */
	if (selectedOne == NULL) {
		return(0);
	} else {
		/*  Reset the key and the string  */
		selectedOne->key = newKey;

		selectedOne->string = (char*) realloc(selectedOne->string, (strlen_ext(newInput)+1)*sizeof(char));
		if (selectedOne->string == NULL) {
			return(0);
		}

		for (handle1=0; handle1<=strlen_ext(newInput); handle1++) {
			if (handle1==strlen_ext(newInput)) {
				*(selectedOne->string + handle1) = '\0';
			} else {
				*(selectedOne->string + handle1) = *(newInput + handle1);
			}
		}
	}

	return(1);
}

/*
 *	collection* getCollectionItem(collection *base, int itemKey);
 *
 *	To get a collection node.
 *
 *	*base	->	a pointer pointed to a collection object,
 *	itemKey		->	a unique integer expression that specifies a key number that can be used 
 *				instead of a positional index to access this new element in the collection.
 */
collection* getCollectionItem(collection *base, int itemKey)
{
	collection *lastOne = NULL;
	collection *selectedOne = NULL;

	/*  Checking input parameters  */
	if (base==NULL) {
		return(NULL);
	}

	/*  Looking for the node  */
	lastOne = base;
	if (lastOne->key == itemKey) {
		selectedOne = lastOne;
	} else {
		while(lastOne->next != NULL) {
			lastOne = lastOne->next;
			if (lastOne->key == itemKey) {
				selectedOne = lastOne;
				break;
			}
		}
	}

	return(selectedOne);
}

/*
 *	int removeCollectionItem(collection *base, int itemKey);
 *
 *	Removes an element from a collection object.
 *
 *	*base	->	a pointer pointed to a collection object,
 *	itemKey		->	a unique integer expression that specifies a key number that can be used 
 *				instead of a positional index to access this new element in the collection.
 */
int removeCollectionItem(collection *base, int itemKey)
{
	collection *selectedOne = NULL;

	/*  Checking input parameters  */
	if (base==NULL) {
		return(0);
	}

	/*  Looking for the node  */
	selectedOne = getCollectionItem(base, itemKey);
	if (selectedOne == NULL) {
		return(0);
	}

	/*  Connecting the previous node and the next node  */
	if (selectedOne->previous != NULL) {
		selectedOne->previous->next = selectedOne->next;
	}

	if (selectedOne->next != NULL) {
		selectedOne->next->previous = selectedOne->previous;
	}

	/*  Destroying the node  */
	free(selectedOne->string);
	free(selectedOne);

	return(1);
}

/*
 *	int getCollectionCount(collection *base);
 *
 *	Gets the number of elements actually contained in the collection. 
 *
 *	*base	->	a pointer pointed to a collection object.
 */
int getCollectionCount(collection *base)
{
	int count;
	collection *lastOne = NULL;

	/*  Checking input parameters  */
	if (base==NULL) {
		return(0);
	}

	/*  Reset the counter*/
	count=1;

	/*  Count the nodes  */
	lastOne = base;
	while(lastOne->next != NULL) {
		lastOne = lastOne->next;
		count++;
	}

	return(count);
}

/*
 *	collection* getLastItem(collection *base);
 *
 *	Gets the last node of a collection object.
 *
 *	*base	->	a pointer pointed to a collection object.
 */
collection* getLastItem(collection *base)
{
	collection *lastOne = NULL;

	/*  Looking for the last node of the collection object  */
	lastOne = base;
	while(lastOne->next != NULL) {
		lastOne = lastOne->next;
	}

	return(lastOne);
}

/*
 *	void freeCollection(collection *base);
 *
 *	Deletes all elements of a collection object.
 *
 *	*base	->	a pointer pointed to a collection object.
 */
void freeCollection(collection *base)
{
	collection *current = NULL, *next = NULL;
	current = base;

	/*  Traversing the collection object  */
	next = NULL;
	while(current != NULL) {
		next = current->next;

		/*  Destroying the node  */
		free(current->string);
		free(current);

		current = next;
	}
}

/*
 *	collection* sliceString(char *source, char *separateChar);
 *
 *	Split the string by specific characters.
 *
 *	*source		->	a string expression,
 *	*separateChar	->	the specific characters.
 */
collection* sliceString(char *source, char *separateChar)
{
	collection *stringClt = NULL;
	collection *returnClt = NULL;
	char *base = NULL;
	char *temp = NULL;
	char *uslTemp = NULL;
	char *refreshString = NULL;
	int lpCount;
	int lpPrevious, lpFirst;

	/*  Just split it, I don't have to describe it any more  */
	lpPrevious = 1;
	base = strtrim_ext(source);
rerouteString:
	uslTemp = strgleft_ext(base, strlen_ext(separateChar));

	if (strcmp_ext(uslTemp, separateChar) == 1) {
		refreshString = strgright_ext(base, strlen_ext(base) - strlen_ext(separateChar));
		if (refreshString == NULL) {
			free(base); free(uslTemp);
			return(NULL);
		}

		free(base);

		base = refreshString;

		goto rerouteString;
	}

	free(uslTemp);

	uslTemp = strgright_ext(base, strlen_ext(separateChar));

	if (strcmp_ext(uslTemp, separateChar) == 1) {
		refreshString = strgleft_ext(base, strlen_ext(base) - strlen_ext(separateChar));
		if (refreshString == NULL) {
			free(base); free(uslTemp);
			return(NULL);
		}

		free(base);

		base = refreshString;

		goto rerouteString;
	}

	free(uslTemp);

	lpCount = 0;
	do {
		lpFirst = strin_ext(1, base, separateChar);
		if (lpFirst == 0) {
			lpCount++;

			if (lpCount == 1) {
				stringClt = addCollection(NULL, base, lpCount);
				if (stringClt == NULL) {
					free(base);
					return(NULL);
				}
			} else {
				returnClt = addCollection(stringClt, base, lpCount);
				if (returnClt == NULL) {
					free(base);
					return(NULL);
				}
			}

			break;
		}

		temp = strmid_ext(base, lpPrevious, lpFirst - lpPrevious);
		if (temp == NULL) {
			free(base);
			return(NULL);
		}

		lpCount++;

		if (lpCount == 1) {
			stringClt = addCollection(NULL, temp, lpCount);
			if (stringClt == NULL) {
				free(temp); free(base);
				return(NULL);
			}
		} else {
			if (addCollection(stringClt, temp, lpCount) == NULL) {
				free(temp); free(base);
				return(NULL);
			}
		}

		free(temp);

		refreshString = strgright_ext(base, strlen_ext(base) - lpFirst);
		if (refreshString == NULL) {
			free(base);
			return(NULL);
		}

		free(base);

		base = refreshString;
	} while(!0);

	free(base);

	return(stringClt);
}

/*
 *	collection* sliceString_expr(char *source, char *separateChar);
 *
 *	Split the string by specific characters in bracket-level 0.
 *
 *	*source		->	a string expression,
 *	*separateChar	->	the specific characters.
 */
collection* sliceString_expr(char *source, char *separateChar)
{
	collection *stringClt = NULL;
	collection *returnClt = NULL;
	char *base = NULL;
	char *temp = NULL;
	char *uslTemp = NULL;
	char *refreshString = NULL;
	int lpCount;
	int lpPrevious, lpFirst;

	/*  Just split it, I don't have to describe it any more  */
	lpPrevious = 1;
	base = strtrim_ext(source);
rerouteString:
	uslTemp = strgleft_ext(base, strlen_ext(separateChar));

	if (strcmp_ext(uslTemp, separateChar) == 1) {
		refreshString = strgright_ext(base, strlen_ext(base) - strlen_ext(separateChar));
		if (refreshString == NULL) {
			free(base); free(uslTemp);
			return(NULL);
		}

		free(base);

		base = refreshString;

		goto rerouteString;
	}

	free(uslTemp);

	uslTemp = strgright_ext(base, strlen_ext(separateChar));

	if (strcmp_ext(uslTemp, separateChar) == 1) {
		refreshString = strgleft_ext(base, strlen_ext(base) - strlen_ext(separateChar));
		if (refreshString == NULL) {
			free(base); free(uslTemp);
			return(NULL);
		}

		free(base);

		base = refreshString;

		goto rerouteString;
	}

	free(uslTemp);

	lpCount = 0;
	do {
		lpFirst = strin_ext_expr(1, base, separateChar);
		if (lpFirst == 0) {
			lpCount++;

			if (lpCount == 1) {
				stringClt = addCollection(NULL, base, lpCount);
				if (stringClt == NULL) {
					free(base);
					return(NULL);
				}
			} else {
				returnClt = addCollection(stringClt, base, lpCount);
				if (returnClt == NULL) {
					free(base);
					return(NULL);
				}
			}

			break;
		}

		temp = strmid_ext(base, lpPrevious, lpFirst - lpPrevious);
		if (temp == NULL) {
			free(base);
			return(NULL);
		}

		lpCount++;

		if (lpCount == 1) {
			stringClt = addCollection(NULL, temp, lpCount);
			if (stringClt == NULL) {
				free(temp); free(base);
				return(NULL);
			}
		} else {
			if (addCollection(stringClt, temp, lpCount) == NULL) {
				free(temp); free(base);
				return(NULL);
			}
		}

		free(temp);

		refreshString = strgright_ext(base, strlen_ext(base) - lpFirst);
		if (refreshString == NULL) {
			free(base);
			return(NULL);
		}

		free(base);

		base = refreshString;
	} while(!0);

	free(base);

	return(stringClt);
}

